//
//  LFileManager.swift
//  AppTest
//
//  Created by lete on 2020/7/16.
//  Copyright © 2020 lete. All rights reserved.
//

import UIKit

class LFileManager: NSObject {

}


enum AppDirectories {
    case documents
    case library
    case libraryCaches
    case temp
    case customPath(path: String)
}
// 本文提供了两种获取路径的方法，返回类型是String，还有一种获取路径的方法返回的是URL，FileManager也提供了通过URL操作文件的相关方法，和通过pathString操作的方法基本是一一对应，感兴趣的同学可以对下面的代码进行替换，使用URL作为路径的返回类型和函数的参数操作文件。
/// MARK: - 获取路径 以下两种方法都可以
struct FilePathUtils {
    //document
    static func documentsDirectoryPath() -> String {
//        return NSSearchPathForDirectoriesInDomains(.userDirectory, .userDomainMask, true).first!
        return NSHomeDirectory().appending("/Documents")
    }

    //library
    static func libraryDirectoryPath() -> String {
//        return NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).first!
        return NSHomeDirectory().appending("/Library")
    }

    //temp
    static func tempDirectoryPath() -> String {
//       return NSTemporaryDirectory()
        return NSHomeDirectory().appending("/tmp")
    }

    //Library/Caches
    static func librayCachesPath() -> String {
//        return NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
        return NSHomeDirectory().appending("/Library/Caches")
    }

    //根据枚举值返回不同的url
    static func setupFilePath(directory: AppDirectories, name: String) -> String {
        return getPath(for: directory) + name
    }

    private static func getPath(for directory: AppDirectories) -> String {
        switch directory {
        case .documents:
            return documentsDirectoryPath()
        case .libraryCaches:
            return librayCachesPath()
        case .library:
            return libraryDirectoryPath()
        case .temp:
            return tempDirectoryPath()
        case .customPath(let path):
            return path
        }
    }
}

/// MARK: - 文件操作
struct FileUtils {

    // MARK: - 创建文件
    static func createFolder(basePath: AppDirectories, folderName: String, createIntermediates: Bool = true, attributes: [FileAttributeKey: Any]? = nil) -> Bool {
        let filePath = FilePathUtils.setupFilePath(directory: basePath, name: folderName)
        let  fileManager = FileManager.default
        do {
            try fileManager.createDirectory(atPath: filePath, withIntermediateDirectories: createIntermediates, attributes: attributes)
            return true
        } catch {
            return false
        }
    }
    
    // MARK: - 创建文件
    static func createFile(filePath: String) -> Bool {
        let  fileManager = FileManager.default
        let exist = fileManager.fileExists(atPath: filePath)
        if !exist {
            let createSuccess = fileManager.createFile(atPath: filePath, contents:nil, attributes:nil)
            print("文件创建结果: \(createSuccess)")
             return true
        }
        else{
             print("文件存在")
            return false
        }
    }

    // MARK: - 写入文件
    // options: 默认先创建一个临时文件，直到文件内容写入成功再导入到目标文件里。 如果为NO，则直接写入目标文件里。
    static func writeFile(content: Data, filePath: String, options: Data.WritingOptions = []) -> Bool {
        do {
            try content.write(to: URL(string: filePath)!, options: options)
            return true
        } catch {
            return false
        }
    }

    // MARK: - 读取文件
    static func readFile(filePath: String) -> Data? {
        let fileContents = FileManager.default.contents(atPath: filePath)
        if fileContents?.isEmpty == false {
            return fileContents
        } else {
            return nil
        }
    }

    // MARK: - 删除文件
    static func deleteFile(filePath: String) -> Bool {
        do {
            try FileManager.default.removeItem(atPath: filePath)
            return true
        } catch {
            return false
        }
    }

    // MARK: - 重命名文件
    static func renameFile(path: AppDirectories, oldName: String, newName: String) -> Bool {
        let oldPath = FilePathUtils.setupFilePath(directory: path, name: oldName)
        let newPath = FilePathUtils.setupFilePath(directory: path, name: newName)
        do {
            try FileManager.default.moveItem(atPath: oldPath, toPath: newPath)
            return true
        } catch {
            return false
        }
    }

    // MARK: - 移动文件
    static func moveFile(fileName: String, fromDirectory: String, toDirectory: String) -> Bool {
        let originPath = FilePathUtils.setupFilePath(directory: .customPath(path: fromDirectory), name: fileName)
        let destinationPath = FilePathUtils.setupFilePath(directory: .customPath(path: toDirectory), name: fileName)
        do {
            try FileManager.default.moveItem(atPath: originPath, toPath: destinationPath)
            return true
        } catch {
            return false
        }
    }

    // MARK: - 拷贝文件
    static func copyFile(fileName: String, fromDirectory: String, toDirectory: String) throws {
        let originPath = FilePathUtils.setupFilePath(directory: .customPath(path: fromDirectory), name: fileName)
        let destinationPath = FilePathUtils.setupFilePath(directory: .customPath(path: toDirectory), name: fileName)
        return try FileManager.default.copyItem(atPath: originPath, toPath: destinationPath)
    }

    // MARK: - 文件是否可写
    static func isWritable(filePath: String) -> Bool {
        if FileManager.default.isWritableFile(atPath: filePath) {
            return true
        } else {
            return false
        }
    }

    // MARK: - 文件是否可读
    static func isReadable(filePath: String) -> Bool {
        if FileManager.default.isReadableFile(atPath: filePath) {
            return true
        } else {
            return false
        }
    }

    // MARK: - 文件是否存在
    static func exists(filePath: String) -> Bool {
        if FileManager.default.fileExists(atPath: filePath) {
            return true
        } else {
            return false
        }
    }

    // MARK: - 获取文件列表
    static func getFilePathList(folderPath: String) -> [String] {
        let fileManager = FileManager.default
        let fileList = try? fileManager.contentsOfDirectory(atPath: folderPath)
        return fileList ?? []
    }
}
